import random

import matplotlib.pyplot as plt
import numpy as np

# 分别以（0,0），（10,10）为中心，以6为偏差，随机产生50个数据点
count = 0
dataset = []
while count < 50:
    x1 = random.uniform(-6, 6)
    y1 = random.uniform(-6, 6)
    if x1 ** 2 + y1 ** 2 <= 36:
        dataset.append([x1, y1])
        count = count + 1

count = 0
while count < 50:
    x2 = random.uniform(4, 16)
    y2 = random.uniform(4, 16)
    if (x2 - 10) ** 2 + (y2 - 10) ** 2 <= 36:
        dataset.append([x2, y2])
        count = count + 1


# 计算欧式距离
def Euclidean_distance(a1, a2):
    return np.sqrt(np.sum((a1 - a2) ** 2))


# 计算离样本数据最近的类
def mindistance(centroid, data):
    d = []
    for i in range(len(centroid)):
        d.append(Euclidean_distance(np.array(centroid[i]), np.array(data)))
    return d.index(min(d))


# 求类的均值
def new_mean(w):
    new_centroid = [[] for i in range(len(w))]
    for i in range(len(w)):
        new_centroid[i] = list(np.mean(w[i], axis=0))
    print('new', new_centroid)
    return new_centroid


# C-Means聚类
def CMeans(dataset, k):
    w = [[] for j in range(k)]
    # 随机选取初始数据中的k个对象作为初始的中心，每个对象代表一个聚类中心
    centroid = random.sample(dataset, k)
    print('init', centroid)
    for i in range(len(dataset)):
        # 把每个样本数据归去中心点离它最近的类
        w[mindistance(centroid, dataset[i])].append(dataset[i])
    new_centroid = new_mean(w)
    w_init = w  # w_init为初始分类
    for j in range(k):
        w_init[j] = np.array(w_init[j])

    # 更新聚类中心：将每个类别中所有对象所对应的均值作为该类别的聚类中心，当聚类中心不改变时输出分类结果
    n = 0
    while new_centroid != centroid:
        w = [[] for j in range(k)]
        print(n)
        centroid = new_centroid
        for i in range(len(dataset)):
            w[mindistance(centroid, dataset[i])].append(dataset[i])
        new_centroid = new_mean(w)
        n = n + 1
    for j in range(k):
        w[j] = np.array(w[j])
    return w_init, w


if __name__ == '__main__':
    w_init, arr_w = np.array(CMeans(dataset, 2))
    # 绘制初始分类和最终分类图像
    a1 = plt.subplot(1, 2, 1)
    a1.scatter(w_init[0][:, 0], w_init[0][:, 1], c='b')
    a1.scatter(w_init[1][:, 0], w_init[1][:, 1], c='g')
    a1.set_title("start")
    a2 = plt.subplot(1, 2, 2)
    a2.scatter(arr_w[0][:, 0], arr_w[0][:, 1], c='b')
    a2.scatter(arr_w[1][:, 0], arr_w[1][:, 1], c='g')
    a2.set_title("end")
    plt.show()
